using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace AutoUpdater
{
    /// <summary>
    /// 配置文件工具
    /// </summary>
    public class ConfHelper
    {
        public const string SECTION_SETTINGS = "SETTINGS";

        /// <summary>
        /// 配置文件存放默认地址
        /// </summary>
        public static string defualtPath => System.AppDomain.CurrentDomain.BaseDirectory + "/" + Path.GetFileNameWithoutExtension(System.AppDomain.CurrentDomain.FriendlyName) + ".ini";

        #region 公共方法
        /// <summary> 
        /// 写入INI文件 
        /// </summary> 
        /// <param name="section">项目名称(如 [TypeName] )</param> 
        /// <param name="key">键</param> 
        /// <param name="value">值</param> 
        /// <param name="isEncrypt">是否将值Base64转码</param>
        /// <param name="filePath">配置文件路径</param>
        /// <returns></returns>
        public static bool WriteValue(string section, string key, string value, bool isEncrypt = false, string filePath = null) {
            return IniWriteValue(section, key, value, isEncrypt, filePath);
        }
        /// <summary> 
        /// 读出INI文件 
        /// </summary> 
        /// <param name="section">项目名称(如 [TypeName] )</param> 
        /// <param name="key">键</param> 
        /// <param name="isEncrypt">是否将值Base64解码</param>
        /// <param name="filePath">配置文件路径</param>
        /// <returns></returns>
        public static string ReadValue(string section, string key, bool isEncrypt = false, string filePath = null) {
            return IniReadValue(section, key, isEncrypt, filePath);
        }
        #endregion

        #region 私有处理

        #region 引入WinApi
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        [DllImport("kernel32.dll")]
        private static extern IntPtr _lopen(string lpPathName, int iReadWrite);

        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr hObject);
        #endregion

        /// <summary> 
        /// 写入INI文件 
        /// </summary> 
        /// <param name="section">项目名称(如 [TypeName] )</param> 
        /// <param name="key">键</param> 
        /// <param name="value">值</param> 
        /// <param name="isEncrypt">是否将值Base64转码</param>
        /// <param name="filePath">配置文件路径</param>
        /// <returns></returns>
        private static bool IniWriteValue(string section, string key, string value, bool isEncrypt, string filePath) {
            //var v = isEncrypt ? ToBase64String(value == null ? "" : value) : value;
            var v = isEncrypt ? EncryptParse.DESEncrypt(value == null ? "" : value, EncryptParse.GenerateDESKey(key)) : value;
            var l = WritePrivateProfileString(section, key, v, filePath ?? ConfHelper.defualtPath);
            return l > 0 ? true : false;
        }

        /// <summary> 
        /// 读出INI文件 
        /// </summary> 
        /// <param name="section">项目名称(如 [TypeName] )</param> 
        /// <param name="key">键</param> 
        /// <param name="isEncrypt">是否将值Base64解码</param>
        /// <param name="filePath">配置文件路径</param>
        private static string IniReadValue(string section, string key, bool isEncrypt, string filePath) {
            StringBuilder v = new StringBuilder(5000);
            var i = GetPrivateProfileString(section, key, "", v, 5000, filePath ?? ConfHelper.defualtPath);
            //return i > 0 ? (isEncrypt ? UnBase64String(v.ToString()) : v.ToString()) : null;
            return i > 0 ? (isEncrypt ? EncryptParse.DESDecrypt(v.ToString(), EncryptParse.GenerateDESKey(key)) : v.ToString()) : null;
        }


        private const int OF_READWRITE = 2;
        private const int OF_SHARE_DENY_NONE = 0x40;
        private static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
        private static bool IsFileOccupied(string filePath) {
            IntPtr vHandle = _lopen(filePath, OF_READWRITE | OF_SHARE_DENY_NONE);
            CloseHandle(vHandle);
            return vHandle == HFILE_ERROR ? true : false;
        }

        /// <summary>
        /// 解码Base64（失败则返回显示值）
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string UnBase64String(string value) {
            try
            {
                if (string.IsNullOrEmpty(value))
                    return "";
                byte[] bytes = Convert.FromBase64String(value);
                return Encoding.UTF8.GetString(bytes);
            }
            catch (Exception)
            {
                return value;
            }

        }

        /// <summary>
        /// 转码Base64（失败则返回显示值）
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string ToBase64String(string value) {
            try
            {
                if (string.IsNullOrEmpty(value))
                    return "";
                byte[] bytes = Encoding.UTF8.GetBytes(value);
                return Convert.ToBase64String(bytes);
            }
            catch (Exception)
            {
                return value;
            }

        }
        #endregion
    }
}
